import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Set;
import java.util.TreeSet;

/*
 * Class for selection
 * and projection logic
 * that is query logic.
 */
public class Selection {

	String[] temp;
	int length;
	int record_length;
	datatype[] datatypes = new datatype[7];
	public static ArrayList <ArrayList<String>> select= new ArrayList<ArrayList<String>>();
	SelectIndex selectIndex = new SelectIndex();
	HashMap<Integer, String> hashMap = new HashMap<Integer, String>();
	RidList ridList = new RidList();
	ArrayList<Long> list;
	//Converting operators to codes
	public String calcop(String temp) throws Exception
	{
		if(temp.equals("="))
			return 0+"";
		else if(temp.equals("<>"))
			return 1+""+2+"";
		else if(temp.equals(">"))
			return 1+"";
		else if(temp.equals("<"))
			return 2+"";
		else if(temp.equals("<="))
			return 20+"";
		else if (temp.equals(">="))
			return 10+"";

		throw new Exception("Invalid operator");

	}
	//Function to perform to evaluate the query
	public void select(String[] array)
	{
		datatypes[0] = new i1();
		datatypes[1] = new i2();
		datatypes[2] = new i4();
		datatypes[3] = new i8();
		datatypes[4] = new r4();
		datatypes[5] = new r8();
		datatypes[6] = new cx();
		String path = array[0];
		
		//Reading header of the heap file containing the schema information.
		ReadHeader readHeader = new ReadHeader();
		try 
		{
			temp = readHeader.read(path);
		} 
		catch (Exception e) 
		{	
			System.out.println(e);
		}
		length =  temp.length;
		record_length = Integer.parseInt(temp[length-1]);
		//System.out.println(record_length);

		//Converting header into a code
		String temp3 [] =new String [length-1];
		for(int i =0;i<temp3.length;i++)
		temp3[i] = temp[i];
		ArrayList<datatype> headerData=convertHeader.convertHeader(temp3);
		heap.f=new File(path);
		boolean project[]=new boolean[headerData.size()];
		
		//Storing the selection and projection condition.
		
		try
		{
			for(int y=0;y<headerData.size();y++)
			{
				select.add(new ArrayList<String>());
			}
			for(int i=1;i<array.length;i++)
			{
				if(array[i].charAt(0)=='-')
				{
					if(array[i].charAt(1)=='s')
					{
						if(i+2<array.length)
						{
							int position = (Integer.parseInt(array[i++].substring(2)))-1;
							String op=calcop(array[i++]);
							//System.out.println(op);
							if(position>select.size())
								throw new Exception("Column doesn't exists");
							select.get(position).add(op);
							select.get(position).add(array[i]);
						}
						else
						{
							throw new Exception("Select condition not full");
						}
					}
					else
					{
						if(array[i].charAt(1)=='p')
						{
							project[array[i].charAt(2)-'0'-1]=true;
						}
						else
						{
							throw new Exception("Wrong query");
						}
					}
				}
				else
				{
					throw new Exception("wrong query");
				}
			}
			hashMap = selectIndex.IntersectedList(temp,path);
			Set<Integer> set = hashMap.keySet();
			Iterator<Integer> itr= set.iterator();
			
			
			int c=0;
			//storing which columns to display.
			for(int i=0;i<project.length;i++)
			{
				if(project[i])
					c++;
			}
			if(c==0)
			{
				Arrays.fill(project, true);
				c=project.length;
			}


			String record[]=new String[headerData.size()];
			boolean firstime = true;
			// Taking each record and checking whether it matches the selection condition or not and writing if it matches.
			int count1=0;
			if(hashMap.size()==0)
			{
				try
				{
					while(heap.readpointer<heap.f.length())
					{
						boolean ch=false;

						for(int j=0;j<headerData.size();j++)
						{
							String data = datatypes[headerData.get(j).type].read(headerData.get(j).length);

							int i=data.indexOf('~');
							if(i!=-1)
								data=data.substring(0,i);

							record[j]=data;

							for(int k=0;k<select.get(j).size();k+=2)
							{
								int com = datatypes[headerData.get(j).type].compares(record[j],select.get(j).get(k+1));
								int length=select.get(j).get(k).length();
								String regex;
								String str;
								str=com+"";
								if(length==2)
									regex=select.get(j).get(k).charAt(0)+""+"|"+select.get(j).get(k).charAt(1)+"";
								else
									regex=select.get(j).get(k).charAt(0)+"";

								if(!str.matches(regex))
								{
									ch=true;
								}
							}
						}

						if(!ch)
						{
							int dis=0;
							if(firstime)
							{
								for(int t=0;t<project.length;t++)
								{
									if(project[t])
									{
										System.out.print(temp[t]);
										dis++;
										if(dis!=c)
										{
											System.out.print(",");
										}
									}
								}
								firstime = false;
								System.out.println();
							}

							count1++;
							dis=0;
							for(int t=0;t<project.length;t++)
							{
								if(project[t])
								{
									System.out.print(record[t]);
									dis++;
									if(dis!=c)
									{
										System.out.print(",");
									}
								}

							}
							System.out.println();

						}


					}
				}
				catch(Exception e)
				{
					e.printStackTrace();
				}

				//System.out.println(count1);
			}
			
			else
			{
				list = ridList.mergedRidList(hashMap, path, headerData);
				ReadNext read = new ReadNext();
				Iterator<Long> it = list.iterator();
				
				for(int m=0; m<list.size();m++)
				{
					long l = it.next().longValue();
					String str2 = read.readNext(l,headerData); //record corresponding to the record ids
					try
					{
							String[] temps = str2.split(",");
							boolean ch=false;

							for(int j=0;j<temps.length;j++)
							{
								String data = temps[j];

								int i=data.indexOf('~');
								if(i!=-1)
									data=data.substring(0,i);

								record[j]=data;

								if(j<select.size())
								{
									for(int k=0;k<select.get(j).size();k+=2)
									{
						
										int com = datatypes[headerData.get(j).type].compares(record[j],select.get(j).get(k+1));
										int length=select.get(j).get(k).length();
										String regex;
										String str;
										str=com+"";
										if(length==2)
											regex=select.get(j).get(k).charAt(0)+""+"|"+select.get(j).get(k).charAt(1)+"";
										else
											regex=select.get(j).get(k).charAt(0)+"";

										if(!str.matches(regex))
										{
											ch=true;
										}
									}

								}
							}

							if(!ch)
							{
								int dis=0;
								if(firstime)
								{
									for(int t=0;t<project.length;t++)
									{
										if(project[t])
										{
											System.out.print(temp[t]);
											dis++;
											if(dis!=c)
											{
												System.out.print(",");
											}
										}
									}
									firstime = false;
									System.out.println();
								}

								count1++;
								dis=0;
								for(int t=0;t<project.length;t++)
								{
									if(project[t])
									{
										System.out.print(record[t]);
										dis++;
										if(dis!=c)
										{
											System.out.print(",");
										}
									}

								}
								System.out.println();

							}


						}
					
				catch(Exception e)
				{
					e.printStackTrace();
				}

			

		
					
			}
				//System.out.println(count1);
			}
			
	}
		catch(Exception e)
		{
			System.out.println(e);
		}
		
	}
	
}
